package com.cy.pj.sys.Service;

import com.cy.pj.sys.commom.annotation自定义注解类.RequiredTime;
import com.cy.pj.sys.dao.SysLogDao;
import com.cy.pj.sys.commom.ServiceException;
import com.cy.pj.sys.dao.SysLogDao;
import com.cy.pj.sys.pojo.SysLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.Operation;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Transactional(readOnly = false,
        timeout = 60, //如果配置了具体时间,则超过该时间限制但事务还没有完成，则自动回滚事务
        rollbackFor = Throwable.class,//出了任何异常都会回滚
        isolation = Isolation.READ_COMMITTED) //事务的隔离级别，默认值采用 DEFAULT
@Slf4j //用注解初始化了日志，后面直接Log调用
@Service //业务层实现类特有的备注
public class SysLogServicelmpl异步处理和事务控制 implements SysLogService {
    @Autowired
    private SysLogDao sysLogDao;


    //有此注解描述的方法为日志切入点方法
    @RequiredTime
    @Override
    public List<SysLog> selectLogsService(SysLog sysLog) {
        //Long start=System.currentTimeMillis();
        //log.info("method start {}",start);
        List<SysLog> list = sysLogDao.selectLogs(sysLog);
        //Long end=System.currentTimeMillis();
//log.info("method end {}", end);
        return list;
    }

    @Override
    public SysLog selectByIdService(Long id) {
        SysLog rest = sysLogDao.selectById(id);
        if (rest == null)
            throw new ServiceException("数据已经不存在了");
        return rest;
    }

    /**
     * @Async注解描述的方法为一个异步切入点方法 使用这个注解时，底层会通过非Tomcat的线程，而是线程池里的新的线程进行调用异步切入点方法
     * @Async注解描述的方法其返回值类型建议为void,假如为非void，你需要对方法返回值类型进行设计， 比如说方法声明为Future<Integer>,那方法内部的返回值格式为： return new AsyncResult<Integer>(返回值内容)
     */
    @Async
    @Override
    public void saveLog(SysLog sysLog) {
        //模拟耗时操作-线程休眠
        try {
            Thread.sleep(10000);
        } catch (Exception e) {
        }

        sysLogDao.insertLog(sysLog);
    }

    //扩展：加备注@Transactional，会让数据回滚：一致性，要么都失败，要么都成功
    @Transactional //此注解描述方法时，这个方法为一个事务切入点方法
    @Override
    public int deleteLogsService(Long... id) {
        //int rows=sysLogDao.deleteLogs(id);
        for (int i = 0; i < id.length; i++) {
            //这里抛出异常时如何让已删除数据的操作回滚
            if (i == 1) { //测试是否会回滚：设置第二个id删除失败
                throw new RuntimeException("删除失败");
            }
            sysLogDao.deleteLogs(id[i]);
        }
        // if(rows==0)
        // throw new ServiceException("记录已经不存在了");
        return 1;
    }
}
